package com.anonymous.util;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

import javax.crypto.Mac;
import javax.crypto.SecretKey;

public class IntegritySecurityUtils {

	/**
	 * MAC Method testing based on professor's code
	 * ***/
	public static byte[] getMAC(Object obj, SecretKey k) {
		try {
			// Serialize to a byte array
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bos);
			out.writeObject(obj);
			out.close();

			// Get the bytes of the serialized object
			byte[] b1 = bos.toByteArray();

			Mac mac = Mac.getInstance("HmacSHA256");
			mac.init(k);
			byte[] t1 = mac.doFinal(b1);

			return t1;

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("HMAC process failed");
			return null;
		}
	}

	/***
	 * Generate the signature of message
	 * 
	 * @param message
	 * @param k
	 * @return the signature of sender's message
	 */
	public byte[] getMessageSignature(Object obj, PrivateKey k) {

		// Hash message (input for signing)
		Mac mac;
		try {
			mac = Mac.getInstance("HmacSHA256");

			mac.init(k);

			// Serialize to a byte array
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bos);
			out.writeObject(obj);
			out.close();

			// Get the bytes of the serialized object
			byte[] b = bos.toByteArray();
			byte[] t1 = mac.doFinal(b);

			// 2. Sign with private key

			Signature sign = Signature.getInstance("SHA256WITHRSA");

			sign.initSign(k);

			sign.update(b);

			// Initial signature
			byte[] s = null;

			s = sign.sign();
			return s;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 
	 * To check if the message has been modified or not
	 * 
	 * @param sig
	 *            signature received from the sender
	 * @param message
	 *            message to versify
	 * @return the result of the signature verification
	 */
	public boolean verifyMesageSignature(byte[] sig, Object obj,
			PublicKey pubKey) {
		try {
			Signature ver = Signature.getInstance("SHA256WITHRSA");
			ver.initVerify(pubKey);

			// Serialize to a byte array
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bos);
			out.writeObject(obj);
			out.close();

			// Get the bytes of the serialized object
			byte[] b = bos.toByteArray();

			ver.update(b);
			boolean verifyResult = ver.verify(sig);
			return verifyResult;

		} catch (Exception e) {
			e.printStackTrace();

		}
		return false;
	}

	public byte[] getHash(byte[] m) {
		try {
			MessageDigest sha = MessageDigest.getInstance("SHA-256");

			// hash = H(m)
			byte[] hash = sha.digest(m);

			return hash;

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Hash failed");
		}
		return null;
	}

}
